package naga.x.db.type;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.util.TypeUtils;

public class PropertyPool extends JSONObject {
	
	public PropertyPool() {
		super(true);
	}
	
	@Override
	public <T> T getObject(String key, Class<T> clazz) {
		Object obj = get(key);
		if (obj == null) {
			return null;
		}
		if (clazz == obj.getClass() || clazz.isAssignableFrom(obj.getClass())) {
			return (T) obj;
		}
		T t;
		if (Set.class.isAssignableFrom(clazz)
				&& obj instanceof List) {
			obj = new LinkedHashSet<>((List) obj);
			t = (T) obj;
		} else {
			try {
				t = TypeUtils.castToJavaBean(obj, clazz);
			} catch (Exception e) {
				String jsonString = obj instanceof String ? (String) obj : JSON.toJSONString(obj);
				t = JSON.parseObject(jsonString, clazz);
			}
		}
		put(key, t);
		return t;
	}

	public <T> List<T> getList(String key, Class<T> clazz) {
		Object val = get(key);
		if (val == null) {
			return null;
		}
		String jsonString = null;
		if (val instanceof JSONArray) {
			jsonString = ((JSONArray) val).toJSONString();
		} else if (val instanceof String) {
			jsonString = (String) val;
		}
		if (jsonString != null) {
			List<T> list = parseArray(jsonString, clazz);
			put(key, list);
			return list;
		}
		return (List<T>) val;
	}
	
	public <T> T getObject(String key, TypeReference<T> type) {
		Object val = get(key);
		if (val == null) {
			return null;
		}
		try {
			Type _type = type.getType();
			if (_type instanceof ParameterizedType) {
				_type = ((ParameterizedType) _type).getRawType();
			}
			if (_type instanceof Class && ((Class) _type).isAssignableFrom(val.getClass())) {
				return (T) val;
			}
//			return TypeUtils.cast(val, type.getType(), ParserConfig.getGlobalInstance());
		} catch (Exception e) {
		}
		String jsonString;
		if (val instanceof JSON) {
			jsonString = ((JSON) val).toJSONString();
		} else if (val instanceof String) {
			jsonString = (String) val;
		} else {
			jsonString = JSON.toJSONString(val);
		}
		if (jsonString != null) {
			T obj = parseObject(jsonString, type);
			put(key, obj);
			return obj;
		}
		return null;
	}
	
	public byte add(String key, byte val) {
		byte newVal = (byte) (getByteValue(key) + val);
		put(key, newVal);
		return newVal;
	}
	
	public short add(String key, short val) {
		short newVal = (short) (getShortValue(key) + val);
		put(key, newVal);
		return newVal;
	}

	public int add(String key, int val) {
		int newVal = getIntValue(key) + val;
		put(key, newVal);
		return newVal;
	}
	
	public long add(String key, long val) {
		long newVal = getLongValue(key) + val;
		put(key, newVal);
		return newVal;
	}
	
	public float add(String key, float val) {
		float newVal = getFloatValue(key) + val;
		put(key, newVal);
		return newVal;
	}
	
	public double add(String key, double val) {
		double newVal = getDoubleValue(key) + val;
		put(key, newVal);
		return newVal;
	}
	
	public byte subtract(String key, byte val) {
		byte newVal = (byte) (getByteValue(key) - val);
		put(key, newVal);
		return newVal;
	}
	
	public short subtract(String key, short val) {
		short newVal = (short) (getShortValue(key) - val);
		put(key, newVal);
		return newVal;
	}

	public int subtract(String key, int val) {
		int newVal = getIntValue(key) - val;
		put(key, newVal);
		return newVal;
	}
	
	public long subtract(String key, long val) {
		long newVal = getLongValue(key) - val;
		put(key, newVal);
		return newVal;
	}
	
	public float subtract(String key, float val) {
		float newVal = getFloatValue(key) - val;
		put(key, newVal);
		return newVal;
	}
	
	public double subtract(String key, double val) {
		double newVal = getDoubleValue(key) - val;
		put(key, newVal);
		return newVal;
	}
	
	public byte getByte(String key, byte defaultVal) {
		Byte val = getByte(key);
		return val != null ? val.byteValue() : defaultVal;
	}
	
	public short getShort(String key, byte defaultVal) {
		Short val = getShort(key);
		return val != null ? val.byteValue() : defaultVal;
	}
	
	public int getInt(String key, int defaultVal) {
		Integer val = getInteger(key);
		return val != null ? val.intValue() : defaultVal;
	}
	
	public long getLong(String key, long defaultVal) {
		Long val = getLong(key);
		return val != null ? val.longValue() : defaultVal;
	}
	
	public float getFloat(String key, float defaultVal) {
		Float val = getFloat(key);
		return val != null ? val.floatValue() : defaultVal;
	}
	
	public double getDouble(String key, double defaultVal) {
		Double val = getDouble(key);
		return val != null ? val.doubleValue() : defaultVal;
	}
	
}
